#include "Map.h"
#include "MapRenderer.h"

#include <QDebug>
#include <QOpenGLBuffer>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QPointF>
#include <QQuickItem>
#include <QQuickWindow>
#include <QRunnable>
#include <QSGFlatColorMaterial>
#include <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGRendererInterface>
#include <QSGSimpleRectNode>
#include <QThread>
#include <QVector3D>

#include <vector_functions.h>

using namespace solar;

Map::Map(QQuickItem* parent)
    : QQuickItem(parent), t_(1.0), renderer_(nullptr), display_x_(0), display_y_(0),
      display_width_(0), display_height_(0), img_resolution_x_(0), img_resolution_y_(0),
      img_boundary_horizontal_dst_(70), x_offset_(0), y_offset_(0)
{
    // setFlag(ItemHasContents, true);
    connect(this, &QQuickItem::windowChanged, this, &Map::windowChanged);
    // connect(renderer_, &MapRenderer::imageCompleted, this, &Map::mapCompleted);
    // connect(this, SLOT(Map::updateImage()), renderer_,
    // SLOT(MapRenderer::reloadTexture())); // 该connect不起作用
}

void Map::updateImage()
{
    qDebug() << "Map updateImage";
    if (window() != nullptr)
    {
        window()->update();
    }
}
void Map::generateTexture(cuda::inter_op::Uchar4* fluxmap_data, int resolution_x, int resolution_y)
{
    renderer_->generateTexture(fluxmap_data, {resolution_x, resolution_y});

    if (window() != nullptr)
    {
        window()->update();
    }
}
void Map::setVisible(bool /*visible*/)
{
    renderer_->setVisible(true);
    if (window() != nullptr)
    {
        window()->update();
    }
}
void Map::mapCompleted()
{
    if (!renderer_->map_completed_)
    {
        qDebug() << "------map::mapcompleted";
        emit mapCompletedSignal();
    }
}

void Map::setScale(qreal scale)
{
    t_ = scale;
    setImageSize();
    renderer_->setViewportSize(QSize(img_width_, img_height_));
    if (window() != nullptr)
    {
        window()->update();
    }
}

void Map::setPos(int x_offset, int y_offset)
{
    bool x_reset = false;
    bool y_reset = false;
    if (x_offset_ != x_offset)
    {
        x_reset = true;
        x_offset_ = x_offset;
        emit xOffsetChanged();
        // renderer_->setX(display_x_ + x_offset_);
    }
    if (y_offset_ != y_offset)
    {
        y_reset = true;
        y_offset_ = y_offset;
        emit yOffsetChanged();
        // renderer_->setY(display_height_ - y_offset_ - img_height_);  //
        // 注意：opengl的y轴正方向是向上的
    }
    if (x_reset || y_reset)
    {
        if (window() != nullptr)
        {
            window()->update();
        }
    }
}

void Map::sync()
{
    qDebug() << "sync";
    if (renderer_ == nullptr)
    {
        renderer_ = new MapRenderer();
        connect(window(), &QQuickWindow::beforeRendering, renderer_, &MapRenderer::init,
                Qt::DirectConnection);
        connect(window(), &QQuickWindow::beforeRenderPassRecording, renderer_, &MapRenderer::paint,
                Qt::DirectConnection);
        connect(window(), &QQuickWindow::afterRendering, this, &Map::mapCompleted,
                Qt::DirectConnection);
        // connect(window(), &QQuickWindow::)
        // connect(renderer_, &MapRenderer::imageCompleted, this, &Map::mapCompleted,
        // Qt::DirectConnection); connect(this, &Map::updateImage, renderer_,
        // &MapRenderer::reloadTexture);

        // connect(window(), &QQuickWindow::beforeRenderPassRecording, renderer_,
        // &MapRenderer::loadTexture, Qt::DirectConnection); connect(window(),
        // &QQuickWindow::afterRendering, renderer_, &MapRenderer::paint, Qt::DirectConnection);
    }
    // renderer_->setViewportSize(window()->size() * window()->devicePixelRatio());

    renderer_->setWindow(window());

    if (display_width_ > 0)
    {

        setImageSize(); // 根据窗口大小及图片分辨率生成img_width_和img_height_
        renderer_->setViewportSize(QSize(img_width_, img_height_));
        renderer_->setT(t_);
        renderer_->setX(display_x_ + x_offset_);
        // renderer_->setY(display_y_ + y_offset_);
        int y = display_height_ - y_offset_ - img_height_;
        renderer_->setY(y);
        renderer_->setResolution(img_resolution_x_, img_resolution_y_);
        // qDebug() <<" sync set properties: img_width="<<img_width_ <<" img_height="<<img_height_
        //             << " display_x="<<display_x_ <<" display_y="<<display_y_
        //             << " display_width="<<display_width_ << " display_height="<<display_height_
        //             <<" x_offset="<<x_offset_ <<" y_offset="<<y_offset_;
    }
}
void Map::cleanup()
{
    if (renderer_ != nullptr)
    {
        delete renderer_;
        renderer_ = nullptr;
    }
}
void Map::windowChanged(QQuickWindow* win)
{
    if (win != nullptr)
    {
        connect(win, &QQuickWindow::beforeSynchronizing, this, &Map::sync, Qt::DirectConnection);
        connect(win, &QQuickWindow::sceneGraphInvalidated, this, &Map::cleanup,
                Qt::DirectConnection);

        // ！！！！---颜色设置，修改！！！
        win->setColor(QColor(255, 255, 255, 0));
    }
}
class CleanupJob : public QRunnable
{
    public:
        CleanupJob(MapRenderer* renderer) : m_renderer(renderer) {}
        void run() override { delete m_renderer; }

    private:
        MapRenderer* m_renderer;
};
void Map::releaseResources()
{
    window()->scheduleRenderJob(new CleanupJob(renderer_), QQuickWindow::BeforeSynchronizingStage);
    renderer_ = nullptr;
}

void Map::setT(qreal t)
{
    if (t == t_)
    {
        return;
    }
    t_ = t;
    emit tChanged();
    // UI动画更新属性值后，调用update刷新
    if (window() != nullptr)
    {
        window()->update();
    }
}

// 按照图片分辨率的比例设置map的大小

void Map::setImageSize()
{
    float index = (float)(img_resolution_x_) / (float)(img_resolution_y_); // 图像的宽高比
    img_height_ = display_height_ - 100;
    img_width_ = (int)(index * img_height_);
    if (img_width_ >
        display_width_ - img_boundary_horizontal_dst_ *
                             2) // 如果高度设置为200会导致宽度超过窗口的话，就把宽度设置为200
    {
        img_width_ = display_width_ - img_boundary_horizontal_dst_ * 2;
        img_height_ = (int)((float)img_width_ / index);
    }

    img_width_ = img_width_ * t_;
    img_height_ = img_height_ * t_;

    emit imgWidthChanged();
    emit imgHeightChanged();

    if (!already_first_set_offset_)
    {

        already_first_set_offset_ = true;
        x_offset_ = (display_width_ - img_width_) / 2;
        y_offset_ = (display_height_ - img_height_) / 2;
        qDebug() << " set imagesize--- x_offset=" << x_offset_ << " y_offset=" << y_offset_;
        // x_offset_ = 10;
        // y_offset_ = 10;
        emit xOffsetChanged();
        emit yOffsetChanged();
    }
}

// QSGNode* Map::updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData *)
// {
//     // auto node = dynamic_cast<QSGSimpleRectNode>(oldNode);

//     // if(!node)
//     // {
//     //     node = new QSGSimpleRectNode();
//     // }

//     QSGGeometryNode * node = nullptr;
//     QSGGeometry *geometry = nullptr;

//     if(!oldNode)
//     {
//         node = new QSGGeometryNode;
//         geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount);
//     geometry->setLineWidth(2);
//     geometry->setDrawingMode(QSGGeometry::DrawLineStrip);
//     node->setGeometry(geometry);
//     node->setFlag(QSGNode::OwnsGeometry);

//     QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
//     material->setColor(QColor(255,0,0));
//     node->setMaterial(material);
//     node->setFlag(QSGNode::OwnsMaterial);
//     }
//     else{
//         node = static_cast<QSGGeometryNode*>(oldNode);
//         geometry = node->geometry();
//         geometry->allocate(m_segmentCount);
//     }
//     QSizeF itemSize = size();
//     QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
//     for (int i = 0; i < m_segmentCount; ++i) {
//         qreal t = i / qreal(m_segmentCount - 1);
//         qreal invt = 1 - t;

//         QPointF pos = invt * invt * invt * m_p1
//                     + 3 * invt * invt * t * m_p2
//                     + 3 * invt * t * t * m_p3
//                     + t * t * t * m_p4;

//         float x = pos.x() * itemSize.width();
//         float y = pos.y() * itemSize.height();

//         vertices[i].set(x, y);
//     }
//     node->markDirty(QSGNode::DirtyGeometry);

//     return node;

//     // geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
//     // geometry->setLineWidth(2);
//     // geometry->setDrawingMode(QSGGeometry::DrawLines);
//     // node->setGeometry(geometry);
//     // node->setFlag(QSGNode::OwnsGeometry);

//     // QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
//     // material->setColor(QColor(255,0,0));
//     // node->setMaterial(material);
//     // node->setFlag(QSGNode::OwnsMaterial);
// }
